package com.decent.common.util.jackson;

import cn.hutool.core.util.StrUtil;
import com.decent.common.constant.DatePatternConstant;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.TimeZone;


/**
 * dao层returnCheck使用的Jackson序列化反序列化Json工具类
 *
 * @author: wangyan
 * @date: 2021/12/16
 */
@Slf4j
@SuppressWarnings("all")
public class ReturnCheckJacksonUtil {
    /**
     * jackson对象
     */
    private static final ObjectMapper MAPPER;
    private static final ObjectMapper OBJECT_SNAKE_CASE_MAPPER;

    static {
        MAPPER = new ObjectMapper();
        JavaTimeModule timeModule = new JavaTimeModule();
        timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
        MAPPER.registerModule(timeModule);
        MAPPER.setTimeZone(TimeZone.getTimeZone(DatePatternConstant.TIMEZONE));
        // 忽略字段不存在导致无法转换的异常
        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 将json中的浮点数解析成BigDecimal对象，禁用后会解析成Double对象
        MAPPER.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
        MAPPER.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);

        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addDeserializer(Enum.class, new EnumDeserializer());
        MAPPER.registerModule(simpleModule);
    }

    static {
        OBJECT_SNAKE_CASE_MAPPER = new ObjectMapper();
        JavaTimeModule timeModule = new JavaTimeModule();
        timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
        OBJECT_SNAKE_CASE_MAPPER.registerModule(timeModule);
        OBJECT_SNAKE_CASE_MAPPER.setTimeZone(TimeZone.getTimeZone(DatePatternConstant.TIMEZONE));
        // 忽略字段不存在导致无法转换的异常
        OBJECT_SNAKE_CASE_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 将json中的浮点数解析成BigDecimal对象，禁用后会解析成Double对象
        OBJECT_SNAKE_CASE_MAPPER.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addDeserializer(Enum.class, new EnumDeserializer());
        OBJECT_SNAKE_CASE_MAPPER.registerModule(simpleModule);

        OBJECT_SNAKE_CASE_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
    }

    /**
     * get ObjectMapper
     */
    public static ObjectMapper getObjectMapper() {
        return MAPPER;
    }

    /**
     * 将对象转换成json字符串
     *
     * @param bean 对象
     * @return json字符串
     */
    public static String beanToJson(Object bean) {
        try {
            return MAPPER.writeValueAsString(bean);
        } catch (JsonProcessingException e) {
            log.error("将对象转换成json字符串异常,{},{}", bean, e.getMessage(), e);
        }
        return "";
    }

    /**
     * 将json结果集转化为对象
     *
     * @param jsonData     json数据
     * @param valueTypeRef TypeReference
     */
    public static <T> T jsonToBean(String jsonData, TypeReference<T> valueTypeRef) {
        if (StrUtil.isBlank(jsonData)) {
            return null;
        }
        try {
            return MAPPER.readValue(jsonData, valueTypeRef);
        } catch (Exception e) {
            log.error("将json结果集转化为对象异常,{},{}", jsonData, e.getMessage(), e);
        }
        return null;
    }

    /**
     * 将json结果集转化为对象
     *
     * @param jsonData json数据
     * @param beanType 对象中的object类型
     */
    public static <T> T jsonToBean(String jsonData, Class<T> beanType) {
        if (StrUtil.isBlank(jsonData)) {
            return null;
        }
        try {
            return MAPPER.readValue(jsonData, beanType);
        } catch (Exception e) {
            log.error("将json结果集转化为对象异常,{},{}", jsonData, e.getMessage(), e);
        }
        return null;
    }

    /**
     * 将json数据转换成pojo对象list
     */
    public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) {
        if (StrUtil.isBlank(jsonData)) {
            return Collections.emptyList();
        }
        JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
        try {
            return MAPPER.readValue(jsonData, javaType);
        } catch (Exception e) {
            log.error("将json数据转换成pojo对象list异常,{},{}", jsonData, e.getMessage(), e);
        }
        return null;
    }


    /**
     * 将json数据转换成pojo对象list
     */
    public static <T> List<T> jsonToList(String jsonData, TypeReference<List<T>> valueTypeRef) {
        if (StrUtil.isBlank(jsonData)) {
            return Collections.emptyList();
        }
        try {
            return MAPPER.readValue(jsonData, valueTypeRef);
        } catch (Exception e) {
            log.error("将json数据转换成pojo对象list异常,{},{}", jsonData, e.getMessage(), e);
        }
        return null;
    }

    /**
     * 将json结果集转化为对象（驼峰转换）
     *
     * @param jsonData json数据
     * @param beanType 对象中的object类型
     */
    public static <T> T jsonToBeanSnakeCase(String jsonData, Class<T> beanType) {
        if (StrUtil.isBlank(jsonData)) {
            return null;
        }
        try {
            return OBJECT_SNAKE_CASE_MAPPER.readValue(jsonData, beanType);
        } catch (Exception e) {
            log.error("将json结果集转化为对象异常,{},{}", jsonData, e.getMessage(), e);
        }
        return null;
    }

    /**
     * 将对象转换成json字符串
     *
     * @param bean 对象
     * @return json字符串
     */
    public static String beanToJsonSnakeCase(Object bean) {
        try {
            return OBJECT_SNAKE_CASE_MAPPER.writeValueAsString(bean);
        } catch (JsonProcessingException e) {
            log.error("将对象转换成json字符串异常,{},{}", bean, e.getMessage(), e);
        }
        return "";
    }


    /**
     * 将json结果集转化为对象
     *
     * @param jsonData     json数据
     * @param valueTypeRef TypeReference
     */
    public static <T> T jsonToBeanSnakeCase(String jsonData, TypeReference<T> valueTypeRef) {
        if (StrUtil.isBlank(jsonData)) {
            return null;
        }
        try {
            return OBJECT_SNAKE_CASE_MAPPER.readValue(jsonData, valueTypeRef);
        } catch (Exception e) {
            log.error("将json结果集转化为对象异常,{},{}", jsonData, e.getMessage(), e);
        }
        return null;
    }

    /**
     * 判断是否为json
     *
     * @param json json数据字符串
     * @return 结果
     */
    public static boolean isJson(String json) {
        String[] jsonStart = {"{", "[{"};
        String[] jsonEnd = {"}", "}]"};
        try {
            if (!StrUtil.startWithAny(json, jsonStart) && !StrUtil.endWithAny(json, jsonEnd)) {
                return false;
            }
            MAPPER.readValue(json, new TypeReference<Object>() {
            });
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
